package com.bestcem.xm.member.dao.impl.mysql;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.sql.SQLConditionCompiler;
import com.bestcem.xm.common.core.uitls.StringUtil;
import com.bestcem.xm.member.dao.ProjectDao;
import com.bestcem.xm.member.dao.mapper.MemberProjectMapper;
import com.bestcem.xm.member.entity.mongo.Project;
import com.bestcem.xm.member.entity.mysql.MemberProjectEntity;
import com.bestcem.xm.member.entity.pojo.ProjectDO;
import com.bestcem.xm.member.service.dto.ProjectMemberDto;
import com.bestcem.xm.member.service.param.ProjectManagerDynamicSql;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 联系人项目持久层实现类
 *
 * @author dc.wang <dc.wang@idiaoyan.com>
 * @version V1.0
 * @date 2021/7/19
 */
@Repository
public class ProjectDaoImpl implements ProjectDao {
    private final MemberProjectMapper memberProjectMapper;

    private SQLConditionCompiler sqlConditionCompiler = SQLConditionCompiler.newInstance();

    @Autowired
    public ProjectDaoImpl(MemberProjectMapper memberProjectMapper) {
        this.memberProjectMapper = memberProjectMapper;
    }

    @Override
    public @NotNull boolean existsProjectName(@NotNull String orgId, @NotBlank String projectName) {
        return false;
    }

    @Override
    public @NotNull boolean existsProjectCode(@NotNull String orgId, @NotBlank String projectCode) {
        return false;
    }

    /**
     * 查询具有相同名称或编号的项目
     *
     * @param orgId 企业id
     * @param name  项目名称
     * @param code  项目编号
     * @return com.bestcem.xm.member.entity.pojo.ProjectDo
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/10/11 14:35
     */
    @Nullable
    @Override
    public ProjectDO findByNameOrCode(@NotNull String orgId, String name, String code) {
        if (!StringUtils.hasText(name) && !StringUtils.hasText(code)) {
            return null;
        }
        return convertEntityToDo(memberProjectMapper.findByNameOrCode(orgId, name, code));
    }

    /**
     * 根据项目id查询项目信息
     *
     * @param orgId 组织标识
     * @param id    项目id
     * @return com.bestcem.xm.member.entity.pojo.ProjectDo
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/10/11 14:36
     */
    @Nullable
    @Override
    public ProjectDO findById(@NotNull String orgId, @NotNull String id) {
        MemberProjectEntity memberProjectEntity = memberProjectMapper.selectByProjectId(id);
        if (memberProjectEntity != null) {
            return convertEntityToDo(memberProjectEntity);
        }
        return null;
    }

    /**
     * 根据项目id列表和企业标识查询项目列表
     *
     * @param orgId 企业标识
     * @param ids   项目id集合
     * @return java.util.List<com.bestcem.xm.member.entity.pojo.ProjectDo>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/10/11 14:42
     */
    @Nullable
    @Override
    public List<ProjectDO> findByIds(@NotNull String orgId, @NotEmpty Collection<String> ids) {
        List<MemberProjectEntity> projectEntities = memberProjectMapper.selectByProjectIdsAndOrgId(ids, orgId);
        return convertEntitysToDos(projectEntities);
    }

    /**
     * 查询项目ids对应的项目
     * 注：该接口未校验企业id
     *
     * @param ids 项目id集合
     * @return 如果不存在，返回EmptyList
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Nullable
    @Override
    public List<ProjectDO> findByIds(@NotEmpty Collection<String> ids) {
        List<MemberProjectEntity> projectEntities = memberProjectMapper.selectByProjectIdsAndOrgId(ids, null);
        return convertEntitysToDos(projectEntities);
    }

    /**
     * 查询名称对应的项目
     *
     * @param orgId       企业标识
     * @param projectName 项目名称
     * @return 项目信息
     * @author yf.wang <yf.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public ProjectDO findByName(String orgId, String projectName) {
        MemberProjectEntity memberProjectEntity = new MemberProjectEntity();
        memberProjectEntity.setOrgId(orgId);
        memberProjectEntity.setName(projectName);
        List<MemberProjectEntity> projectEntities = memberProjectMapper.selectByProjectEntity(memberProjectEntity);
        if (CollectionUtils.isEmpty(projectEntities)) {
            return null;
        }

        return convertEntityToDo(projectEntities.get(0));
    }

    /**
     * 查询编号对应的项目
     *
     * @param orgId 企业标识
     * @param code  项目编号
     * @return 项目信息
     * @author yf.wang <yf.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public List<ProjectDO> findByCode(String orgId, String code) {
        MemberProjectEntity memberProjectEntity = new MemberProjectEntity();
        memberProjectEntity.setOrgId(orgId);
        memberProjectEntity.setCode(code);
        List<MemberProjectEntity> projectEntities = memberProjectMapper.selectByProjectEntity(memberProjectEntity);
        return convertEntitysToDos(projectEntities);
    }

    /**
     * 查询联系人项目数
     *
     * @param orgId    企业标识
     * @param memberId 联系人标识
     * @return 项目数量
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public @NotNull Integer countByMemberId(@NotNull String orgId, @NotNull String memberId) {
        return memberProjectMapper.countByMemberId(orgId, memberId);
    }

    /**
     * 分页查询联系人项目
     *
     * @param orgId    企业id
     * @param memberId 联系人id
     * @param offset   偏移量
     * @param size     大小
     * @return 如果不存在，返回EmptyList
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public @NotNull List<ProjectDO> listByMemberId(@NotNull String orgId, @NotNull String memberId, Integer offset, Integer size) {
        List<MemberProjectEntity> projectEntities = memberProjectMapper.listByMemberId(orgId, memberId, offset, size);
        return this.convertEntitysToDos(projectEntities);
    }

    @Override
    public @NotNull Integer countProjectManagerByDynamicSql(ProjectManagerDynamicSql dynamicSql) {
        return memberProjectMapper.countJoinMemberByCondition(dynamicSql, dynamicSql.getWrapper());
    }

    @Override
    public @NotNull List<ProjectMemberDto> listProjectManagerByDynamicSql(ProjectManagerDynamicSql dynamicSql) {
        return memberProjectMapper.listJoinMemberByCondition(dynamicSql, dynamicSql.getWrapper());
    }

    /**
     * 创建联系人项目
     *
     * @param project 项目信息
     * @return 已创建的项目
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public @NotNull ProjectDO insert(@NotNull ProjectDO project) {
        project.setProjectId(StringUtil.getId());
        memberProjectMapper.insertProject(convertDoToEntity(project));
        return project;
    }

    /**
     * 更新项目信息
     * 注：覆盖所有列
     *
     * @param project 项目信息
     * @return 更新列数
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public Integer update(@NotNull ProjectDO project) {
        return memberProjectMapper.updateProjectById(convertDoToEntity(project));
    }

    /**
     * 删除id对应的项目
     *
     * @param id 项目标识
     * @return 删除数量
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public Integer deleteById(@NotBlank String orgId, @NotBlank String id) {
        return memberProjectMapper.batchDeleteByIds(orgId, Collections.singletonList(id));
    }

    /**
     * 删除id集合中包含的项目
     *
     * @param ids 项目id集合
     * @return 删除数量
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public Integer batchDeleteByIds(@NotNull String orgId, @NotEmpty List<String> ids) {
        return memberProjectMapper.batchDeleteByIds(orgId, ids);
    }

    /**
     * 删除企业对应的所有项目
     *
     * @param orgId 企业标识
     * @author yf.wang <yf.wang@idiaoyan.com>
     * @date 2021/9/16
     */
    @Override
    public void deleteByOrgId(String orgId) {
        memberProjectMapper.deleteByOrgId(orgId);
    }

    /**
     * 批量修改扩展字段名
     */
    @Override
    public void batchUpdateFieldName(String orgId, Map<String, String> fieldIdAndNameMap) {
        if (CollectionUtils.isEmpty(fieldIdAndNameMap)) {
            return;
        }

        List<MemberProjectEntity> existsMembers = memberProjectMapper.findExtendExistsMember(orgId);
        List<MemberProjectEntity> newMembers = new ArrayList<>();
        for (MemberProjectEntity member : existsMembers) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getFieldValList());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject jb = JSONObject.parseObject(array.getString(i));
                for(Map.Entry<String, String> fieldAndName : fieldIdAndNameMap.entrySet()) {
                    if (jb != null && fieldAndName.getKey().equals(jb.getString("field_id"))) {
                        jb.put("field_name", fieldAndName.getValue());
                        hasCheck = true;
                        array.set(i, jb);
                    }
                }
            }
            if (hasCheck) {
                member.setFieldValList(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }
        if (!CollectionUtils.isEmpty(newMembers)) {
            memberProjectMapper.updateMemberByField(newMembers);
        }
//            memberProjectMapper.batchUpdateExtendFieldName(orgId, fieldAndName.getKey(), fieldAndName.getValue());
    }

    /**
     * 修改扩展字段枚举值
     */
    @Override
    public void updateMemberFieldEnumValue(String orgId, String fieldId, Object oldValue, Object newValue) {
        if (oldValue == null) {
            return;
        }
        List<MemberProjectEntity> existsMembers = memberProjectMapper.findExtendExistsMember(orgId);
        List<MemberProjectEntity> newMembers = new ArrayList<>();
        for (MemberProjectEntity member : existsMembers) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getFieldValList());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject jb = JSONObject.parseObject(array.getString(i));
                if (jb != null && fieldId.equals(jb.getString("field_id")) && oldValue.toString().equals(jb.getString("field_value"))) {
                    jb.put("field_value", newValue);
                    hasCheck = true;
                    array.set(i, jb);
                }
            }
            if (hasCheck) {
                member.setFieldValList(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }
        if (!CollectionUtils.isEmpty(newMembers)) {
            memberProjectMapper.updateMemberByField(newMembers);
        }

//        memberProjectMapper.batchUpdateExtendFieldValue(orgId, fieldId, oldValue, newValue);
    }

    @Override
    public ProjectDO findOneByOrgIdAndMemberIdAndName(String orgId, String mid, String projectName) {
        MemberProjectEntity entity = memberProjectMapper.findOneByOrgIdAndMemberIdAndName(orgId, mid, projectName);
        return convertEntityToDo(entity);
    }

    @Override
    public void deleteByMemberIds(String orgId, List<String> memberIds) {
        if(!StringUtils.hasText(orgId) || CollectionUtils.isEmpty(memberIds)){
            return;
        }
        memberProjectMapper.deleteByMemberIds(orgId, memberIds);
    }

    @Override
    public boolean existsMemberProjectNameOrCode(String orgId, String memberId, String projectName, String projectCode) {
        if(!StringUtils.hasText(projectCode) && !StringUtils.hasText(projectName)){
            return false;
        }
        Integer count = memberProjectMapper.countByOrgIdAndMemberIdAndProjectNameAndProjectCode(orgId, memberId, projectName, projectCode);
        return count == 0 ? false : true;
    }

    @Override
    public List<ProjectDO> listByOrgId(String orgId) {
        List<MemberProjectEntity> projectEntities = memberProjectMapper.listByOrgId(orgId);
        return this.convertEntitysToDos(projectEntities);
    }

    @Override
    public Integer batchInsert(List<ProjectDO> projects) {
        List<MemberProjectEntity> entities = projects.stream().map(this::convertDoToEntity).collect(Collectors.toList());
        return memberProjectMapper.batchInsert(entities);
    }

    /**
     * 批量删除扩展字段
     */
    @Override
    public void batchDeleteExtendFields(@NotNull String orgId, @NotEmpty Collection<String> fieldIds) {
        if(CollectionUtils.isEmpty(fieldIds)){
            return;
        }
        List<MemberProjectEntity> existsMembers = memberProjectMapper.findExtendExistsMember(orgId);
        List<MemberProjectEntity> newMembers = new ArrayList<>();
        for (MemberProjectEntity member : existsMembers) {
            boolean hasCheck = false;
            JSONArray array = JSONArray.parseArray(member.getFieldValList());
            if (array == null) {
                continue;
            }
            for (int i = 0; i < array.size(); i++) {
                JSONObject jb = JSONObject.parseObject(array.getString(i));
                if (jb != null && fieldIds.contains(jb.getString("field_id"))) {
                    array.remove(i);
                    hasCheck = true;
                    i--;
                }
            }
            if (hasCheck) {
                member.setFieldValList(JSONArray.toJSONString(array));
                newMembers.add(member);
            }
        }
        if (!CollectionUtils.isEmpty(newMembers)) {
            memberProjectMapper.updateMemberByField(newMembers);
        }

       /* for(String fieldId : fieldIds){
            memberProjectMapper.batchDeleteExtendField(orgId, fieldId);
        }*/
    }

    /**
     * 预处理condition，包括字段名、参数
     *
     * @param jsonConditionUnit 最小单位condition
     */
    /*private void preprocessingUnitCondition(JSONObject jsonConditionUnit) {
        // 来源
        String source = "project".equals(jsonConditionUnit.getString("source")) ? "ds_member_project." : "ds_member_member.";
        jsonConditionUnit.put("source", source);
        // 字段名
        String fieldName = jsonConditionUnit.getString("name");

        // 兼容前端参数命名
        if (fieldName.startsWith("member.")) {
            fieldName = fieldName.substring("member.".length());
        }
        // 获取前端参数映射到表的列名
        String columnName = "ds_member_project.".equals(source) ? MysqlOperatorMapper.projectColumnMapping(fieldName) : MysqlOperatorMapper.memberColumnMapping(fieldName);

        // 特殊字段名
        if ("field_val_list.field_value".equals(columnName)) {
            columnName = String.format("%s -> '$.%s'", "field_val_list", "field_value");
        } else if ("store_id".equals(columnName)) {
            JSONArray values = jsonConditionUnit.getJSONArray("value");
            jsonConditionUnit.put("value", values.getString(values.size() - 1));
        } else if (columnName.startsWith("address")) {
            columnName = String.format("%s -> '$[%s]'", "address", columnName.charAt(columnName.length() - 1));
        }
        jsonConditionUnit.put("name", columnName);
    }*/

    /**
     * entity 转 do
     *
     * @param memberProjectEntity 联系人项目信息entity
     * @return com.bestcem.xm.member.entity.pojo.ProjectDo
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/10/11 14:29
     */
    private ProjectDO convertEntityToDo(MemberProjectEntity memberProjectEntity) {
        if (null == memberProjectEntity) {
            return null;
        }
        return BeanUtil.toBean(memberProjectEntity, ProjectDO.class);
    }

    /**
     * entities 转 dos
     *
     * @param projectEntities 联系人项目信息列表entity
     * @return java.util.List<com.bestcem.xm.member.entity.pojo.ProjectDo>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/10/11 14:39
     */
    private List<ProjectDO> convertEntitysToDos(List<MemberProjectEntity> projectEntities) {
        if (CollectionUtils.isEmpty(projectEntities)) {
            return new ArrayList<>(0);
        }
        return projectEntities.stream().map(this::convertEntityToDo).collect(Collectors.toList());
    }

    /**
     * do 转 entity
     *
     * @param projectDo 联系人项目信息
     * @return com.bestcem.xm.member.entity.mysql.ProjectEntity
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2021/10/11 15:08
     */
    private MemberProjectEntity convertDoToEntity(ProjectDO projectDo) {
        if (null == projectDo) {
            return null;
        }

        return BeanUtil.toBean(projectDo, MemberProjectEntity.class);
    }

    private MemberProjectEntity convert(Project project){
        MemberProjectEntity projectEntity = new MemberProjectEntity();
        projectEntity.setProjectId(project.getId());
        projectEntity.setOrgId(project.getOrgId());
        if(project.getMemberId() != null){
            projectEntity.setMemberId(project.getMemberId().toString());
        }
        projectEntity.setCode(project.getCode());
        projectEntity.setName(project.getName());
        projectEntity.setType(project.getType());
        projectEntity.setStatus(project.getStatus());
        projectEntity.setAccountManager(project.getAccountManager());
        projectEntity.setProjectManager(project.getProjectManager());
        projectEntity.setProjectManagerPhone(project.getProjectManagerMobile());
        projectEntity.setContractNo(project.getContractNo());
        projectEntity.setContractObj(project.getContractObj());
        if(project.getContractMoney() != null){
            projectEntity.setContractMoney(project.getContractMoney().intValue());
        }
        projectEntity.setProjectTime(project.getProjectTime());
        projectEntity.setProgramStartTime(project.getProgramStartTime());
        projectEntity.setActualStartTime(project.getActualStartTime());
        projectEntity.setAcceptanceTime(project.getAcceptanceTime());
        if(!CollectionUtils.isEmpty(project.getExtendFieldValues())){
            projectEntity.setFieldValList(JSONObject.toJSONString(project.getExtendFieldValues()));
        }
        if(project.getCreateTime() != null){
            projectEntity.setCreateTime(project.getCreateTime());
        }
        if(project.getUpdateTime() != null){
            projectEntity.setUpdateTime(project.getUpdateTime());
        }
        return projectEntity;
    }
}
